package com.winchain.chainbill.basic.invoice.service.impl;

import java.text.ParseException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.invoince.po.InvDfr;
import com.shell.bee.invoince.service.InvDfrService;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.SysDateUtil;
import com.winchain.chainbill.basic.invoice.dao.InvoiceDeferedDao;
import com.winchain.chainbill.basic.invoice.rx.BillInvoiceDeferedRejectMsgSubcriber;
import com.winchain.chainbill.basic.invoice.rx.BillInvoiceDfrOverdueUploadSubscriber;
import com.winchain.chainbill.basic.invoice.rx.BillInvoiceDfrUploadUpdateSubscriber;
import com.winchain.chainbill.basic.invoice.rx.TBillInvoiceDeferedRejectMsgSubcriber;
import com.winchain.chainbill.basic.invoice.rx.TBillInvoiceDfrOverdueUploadSubscriber;
import com.winchain.chainbill.basic.invoice.rx.TBillInvoiceDfrUploadUpdateSubscriber;
import com.winchain.chainbill.basic.invoice.service.InvoiceDeferedService;
import com.winchain.chainbill.basic.invoice.vo.InvoiceDeferedVo;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.base.service.CbRecService;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillEvent;
import com.winchain.chainbill.bill.biz.send.rx.BillInvoiceRejectSubscriber;
import com.winchain.chainbill.risk.utill.RateUtil;
import com.winchain.chainbill.tbill.base.po.TbDct;
import com.winchain.chainbill.tbill.base.po.TbRec;
import com.winchain.chainbill.tbill.base.service.TbDctService;
import com.winchain.chainbill.tbill.base.service.TbRecService;
import com.winchain.chainbill.tbill.biz.TBill;
import com.winchain.chainbill.tbill.biz.TBillEvent;
import com.winchain.chainbill.tbill.biz.rx.TBillRjctUpdateAttSubscriber;

import rx.Observable;

@Service
public class InvoiceDeferedServiceImpl implements InvoiceDeferedService {
	@Autowired
	private InvDfrService invDfrService;
	@Autowired
	private InvoiceDeferedDao invoiceDeferedDao;
	@Autowired
	private CbDctService cbDctService;
	@Autowired
	private CbRecService cbRecService;
	@Autowired
	private BillInvoiceDfrUploadUpdateSubscriber billInvoiceDfrUploadUpdateSubscriber;
	@Autowired
	private BillInvoiceDfrOverdueUploadSubscriber billInvoiceDfrOverdueUploadSubscriber;
	@Autowired
	private TbDctService tbDctService;
	@Autowired
	private TbRecService tbRecService;
	@Autowired
	private TBillInvoiceDfrUploadUpdateSubscriber tBillInvoiceDfrUploadUpdateSubscriber;
	@Autowired
	private TBillInvoiceDfrOverdueUploadSubscriber tBillInvoiceDfrOverdueUploadSubscriber;
	@Autowired
	private BillInvoiceRejectSubscriber billInvoiceRejectSubscriber;
	@Autowired
	private TBillRjctUpdateAttSubscriber tBillRjctUpdateAttSubscriber;
	@Autowired
	private BillInvoiceDeferedRejectMsgSubcriber billInvoiceDeferedRejectMsgSubcriber;
	@Autowired
	private TBillInvoiceDeferedRejectMsgSubcriber tBillInvoiceDeferedRejectMsgSubcriber;

	public InvDfr saveInvDfr(String bizId, String bizType, int cusDfrDays, String grpId, String senderId,
			String applyDate, int dctDays) {
		InvDfr invDfr = new InvDfr();
		invDfr.setDfrId(SystemUtil.getUUID());
		invDfr.setState("0");
		invDfr.setBizType(bizType);
		invDfr.setBizId(bizId);
		invDfr.setCusDfrDays(Integer.valueOf(cusDfrDays));

		String ivUploadLimitDay = RateUtil.getInvoiceUploadLimitDays(grpId, grpId, senderId, "iv_upload_limit_day");
		if (StringUtil.emptyAndNull(ivUploadLimitDay)) {
			throw new UnCheckMsgException("��������������");
		}
		int dfrDays = Integer.parseInt(ivUploadLimitDay);
		invDfr.setDfrDays(Integer.valueOf(dfrDays));

		String ivUploadGracePeriod = RateUtil.getInvoiceUploadGracePeriod(grpId, grpId, senderId,
				"iv_upload_grace_period");
		int gracePeriod = Integer.parseInt(ivUploadGracePeriod);
		invDfr.setGracePeriod(Integer.valueOf(gracePeriod));
		if (StringUtil.emptyAndNull(ivUploadGracePeriod)) {
			throw new UnCheckMsgException("����������������");
		}
		if (cusDfrDays > dctDays - gracePeriod - 1) {
			throw new UnCheckMsgException("��������������X������������");
		}
		invDfr.setApplyDate(applyDate);
		String dfrUploadDate;
		String dfrUploadExpDate;
		try {
			dfrUploadDate = SysDateUtil.getPreDay(applyDate, cusDfrDays);
			dfrUploadExpDate = SysDateUtil.getPreDay(dfrUploadDate, gracePeriod);
		} catch (ParseException e) {
			throw new UnCheckMsgException("��������������" + e.getMessage());
		}
		invDfr.setDfrUploadDate(dfrUploadDate);
		invDfr.setDfrUploadExpDate(dfrUploadExpDate);
		this.invDfrService.save(invDfr);
		return invDfr;
	}

	@Pagination
	public List<InvoiceDeferedVo> selectInvoiceByPage(PageLimit limit, InvoiceDeferedVo invoiceDeferedVo) {
		invoiceDeferedVo.setFinId(CommonDataUtil.getCurEntId());
		if (StringUtil.notEmpty(invoiceDeferedVo.getSenderNm())) {
			invoiceDeferedVo.setSenderNm(StringUtil.getParameterLike(invoiceDeferedVo.getSenderNm()));
		}
		if (StringUtil.notEmpty(invoiceDeferedVo.getSellerNm())) {
			invoiceDeferedVo.setSellerNm(StringUtil.getParameterLike(invoiceDeferedVo.getSellerNm()));
		}
		return this.invoiceDeferedDao.selectBasInvoicesForMgtByPage(invoiceDeferedVo);
	}

	public String pass(String bizId, String bizType) {
		if ("1".equals(bizType)) {
			passBill(bizId);
		} else {
			passTBill(bizId);
		}
		return null;
	}

	private void passTBill(String bizId) {
		TBill<TbDct> bill = getTBill(bizId);
		TBillEvent<TbDct> event = new TBillEvent(bill);
		event.setValue("dfrState", "1");
		Observable<TBillEvent<TbDct>> observers = Observable.just(event);
		observers.subscribe(this.tBillInvoiceDfrUploadUpdateSubscriber);
		observers.subscribe(this.tBillInvoiceDfrOverdueUploadSubscriber);
	}

	private void passBill(String bizId) {
		Bill<CbDct> bill = getBill(bizId);
		BillEvent<CbDct> event = new BillEvent(bill);
		event.setValue("dfrState", "1");
		Observable<BillEvent<CbDct>> observers = Observable.just(event);
		observers.subscribe(this.billInvoiceDfrUploadUpdateSubscriber);
		observers.subscribe(this.billInvoiceDfrOverdueUploadSubscriber);
	}

	public String reject(String bizId, String bizType, String remark) {
		if ("1".equals(bizType)) {
			rejectBill(bizId, remark);
		} else {
			rejectTBill(bizId, remark);
		}
		return null;
	}

	private void rejectTBill(String bizId, String remark) {
		TBill<TbDct> bill = getTBill(bizId);
		TBillEvent<TbDct> event = new TBillEvent(bill);
		event.setValue("dfrState", "0");
		event.setValue("bizId", bizId);
		event.setValue("invType", "5");
		event.setValue("remark", remark);
		Observable<TBillEvent<TbDct>> observers = Observable.just(event);
		observers.subscribe(this.tBillInvoiceDfrUploadUpdateSubscriber);
		observers.subscribe(this.tBillRjctUpdateAttSubscriber);
		observers.subscribe(this.tBillInvoiceDeferedRejectMsgSubcriber);
	}

	private TBill<TbDct> getTBill(String bizId) {
		TbDct dct = (TbDct) this.tbDctService.selectByKey(bizId);
		TbRec rec = (TbRec) this.tbRecService.selectByKey(dct.getBillId());
		TBill<TbDct> bill = new TBill();
		bill.setRec(rec);
		bill.setSource(dct);
		return bill;
	}

	private void rejectBill(String bizId, String remark) {
		Bill<CbDct> bill = getBill(bizId);
		BillEvent<CbDct> event = new BillEvent(bill);
		event.setValue("dfrState", "0");
		event.setValue("bizId", bizId);
		event.setValue("invType", "4");
		event.setValue("remark", remark);
		Observable<BillEvent<CbDct>> observers = Observable.just(event);
		observers.subscribe(this.billInvoiceDfrUploadUpdateSubscriber);
		observers.subscribe(this.billInvoiceRejectSubscriber);
		observers.subscribe(this.billInvoiceDeferedRejectMsgSubcriber);
	}

	private Bill<CbDct> getBill(String bizId) {
		CbDct dct = (CbDct) this.cbDctService.selectByKey(bizId);
		CbRec rec = (CbRec) this.cbRecService.selectByKey(dct.getPrntId());
		Bill<CbDct> bill = new Bill();
		bill.setRec(rec);
		bill.setSource(dct);
		return bill;
	}
}
